import flask
import configparser
import os
import logging
import sys
from flask import send_from_directory, abort, request
import argparse
import click
from backend import servercore as svccore
import subprocess
# 创建解析器
import random
def run_shell_command(command):
    try:
        # 执行命令并捕获输出
        result = subprocess.run(
            command,
            shell=True,
            check=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        # 返回标准输出
        return {
            "status": "success",
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.CalledProcessError as e:
        # 命令执行失败时返回错误信息
        return {
            "status": "error",
            "stdout": e.stdout,
            "stderr": e.stderr,
            "return_code": e.returncode
        }
parser = argparse.ArgumentParser(description="服务器详细配置")
parser.add_argument("--config", action="store_true")
parser.add_argument("--dir", type=str, help="输入服务器文件配置目录")
parser.add_argument("--ban", type=str, help="输入ip,加入黑名单")
parser.add_argument("--unban", type=str, help="输入ip,移出黑名单")
args = parser.parse_args()

if not os.path.exists("Serverconf"):
    with open("Serverconf", "w") as f:
        f.write("")
with open("Serverconf", "r+") as f:
    if args.config:
        f.write(args.dir)
        exit
    a = f.read()
    if not a:
        if not os.path.exists("server_conf"):
            print("第一次配置服务器，请先使用命令\'本文件 --config --dir [dir]配置服务器配置目录")
            exit()
        else:
            base = "."
    else:
        base = a
app = flask.Flask(__name__)
cf = configparser.ConfigParser()
cf.read(base + '/server_conf/server.conf')
ban = configparser.ConfigParser()
ban.read(base + '/server_conf/user.conf')
# 确保静态文件目录存在
static_dir = os.path.join(app.root_path, 'static')
os.makedirs(static_dir, exist_ok=True)
if args.ban:
    y = ban.get("ban", 'ip')
    y = y + "," + args.ban
    ban.set("ban", 'ip', y)
    with open(base + '/server_conf/user.conf', 'w') as f:
        ban.write(f)
        click.secho(f"已添加IP {args.ban} 到黑名单", fg='green')
        exit()
if args.unban:
    y = ban.get("ban", 'ip')
    y = y.replace("," + args.unban, "")
    ban.set("ban", 'ip', y)
    with open(base + '/server_conf/user.conf', 'w') as f:
        ban.write(f)
        click.secho(f"已从黑名单中移除IP {args.unban}", fg='green')
        exit()
passkey = str(random.randint(11111111, 99999999))
click.secho("操作密钥: " + passkey, fg="red")
# 日志配置
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='app.log',
    filemode='a'
)

@app.route('/')
def index():
    if request.remote_addr not in ban.get('ban', 'ip').split(','):
        with open(cf.get("Server", 'root') + '/index.html', 'r') as f:
            return f.read()
    else:
        return '<h1>403 Forbidden</h1><p>You have been banned from this server. Please contact the administrator</p>'

@app.route('/favicon.ico')
def favicon():
    try:
        return send_from_directory(static_dir, 'favicon.ico', mimetype='image/vnd.microsoft.icon')
    except FileNotFoundError:
        abort(404)
@app.route('/<path:file_path>')
def handle_connection(file_path):
    if request.remote_addr not in ban.get('ban', 'ip').split(','):
        pass
    else:
        return '<h1>403 Forbidden</h1><p>You have been banned from this server. Please contact the administrator</p>'
    try:
        root_dir = cf.get('Server', 'root')
        full_path = os.path.join(root_dir, file_path)
        
        # 安全检查：防止目录遍历攻击
        if not os.path.abspath(full_path).startswith(os.path.abspath(root_dir)):
            abort(403)
            
        logging.info(f"Requested file: {file_path}")
        
        with open(full_path, 'r') as f:
            return f.read()
            
    except FileNotFoundError:
        logging.error(f"File not found: {file_path}")
        abort(404)
    except PermissionError:
        logging.error(f"Permission denied: {file_path}")
        abort(403)
    except Exception as e:
        logging.error(f"Error accessing {file_path}: {str(e)}")
        abort(500)
@app.route('/info')
def info():
    return svccore.svinfo(cf.get('Server', 'port'))
@app.route(f'/execute/{passkey}')
def execute():
    if cf.get("extension", "remote") == "Enable":
        res = run_shell_command(request.args.get('cmd', 1, type=str))
        return res['stdout']
    return "Remote is not supported"
def run():
    app.run(host='0.0.0.0', port=cf.get('Server', 'port'))
run()